package com.jrauto.CarAppBackend.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jrauto.CarAppBackend.entity.dto.CarQueryDTO;
import com.jrauto.CarAppBackend.entity.vo.CarListVO;
import com.jrauto.CarAppBackend.entity.vo.CarVO;
import com.jrauto.CarAppBackend.entity.vo.MyCarListVO;
import com.jrauto.CarAppBackend.mapper.CarMediaMapper;
import com.jrauto.CarAppBackend.entity.Car;
import com.jrauto.CarAppBackend.entity.CarMedia;
import com.jrauto.CarAppBackend.service.CarService;
import com.jrauto.CarAppBackend.mapper.CarMapper;
import com.jrauto.CarAppBackend.service.CosService;
import jakarta.annotation.Resource;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author huimin
 * @description 针对表【cars(二手车主表)】的数据库操作Service实现
 * @createDate 2025-06-27 15:58:44
 */
@Service
public class CarServiceImpl extends ServiceImpl<CarMapper, Car>
        implements CarService {

    @Resource
    private CarMapper carMapper;


    @Resource
    private CarMediaMapper carMediaMapper;

    @Resource
    private CosService cosService; // 注入COS服务

    @Value("${tencent.cos.webUrl}")
    private String cosWebUrl; // COS访问地址，用于从URL解析COS Key


    /**
     * 从COS URL中解析出COS Key
     *
     * @param imageUrl COS的完整URL
     * @return COS Key
     */
    private String extractCosKeyFromUrl(String imageUrl) {
        if (imageUrl == null || !imageUrl.startsWith(cosWebUrl)) {
            return null; // 非法URL或不属于当前COS配置
        }
        return imageUrl.replace(cosWebUrl, "");
    }

    @Override
    @Transactional // 开启事务
    public Car addCar(Car car, List<String> imageUrls) {
        car.setCarNumber(generateRandomCarNumber());
        // 1. 保存车辆文字信息
        car.setCreatedAt(new Date());
        car.setUpdatedAt(new Date());
        carMapper.insert(car); // Mybatis-Plus 会自动回填 carId

        if (car.getCarId() == null) {
            throw new RuntimeException("保存车辆信息失败，无法获取车辆ID。");
        }

        // 2. 保存车辆图片信息
        if (imageUrls != null && !imageUrls.isEmpty()) {
            List<CarMedia> mediaList = new ArrayList<>();
            for (int i = 0; i < imageUrls.size(); i++) {
                String imageUrl = imageUrls.get(i);
                CarMedia media = new CarMedia();
                media.setCarId(car.getCarId());
                media.setType(1); // 默认为图片类型
                media.setUrl(imageUrl);
//                media.setCreatedAt(new Date());

                media.setOrderIndex(i + 1); // 设置排序
                carMediaMapper.insert(media);
                mediaList.add(media);
            }
        }
        return car;
    }


    @Override
    @Transactional // 开启事务
    public boolean updateCar(Car car, List<String> newImageUrls) {
        // 1. 更新车辆文字信息
        car.setUpdatedAt(new Date());
        int rowsAffected = carMapper.updateById(car);
        if (rowsAffected == 0) {
            return false; // 车辆不存在或更新失败
        }

        // 2. 处理图片信息更新
        Integer carId = car.getCarId();
        // 获取当前车辆的所有媒体记录
        QueryWrapper<CarMedia> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("car_id", carId);
        List<CarMedia> oldMediaList = carMediaMapper.selectList(queryWrapper);

        // 提取旧的图片URL集合
        Set<String> oldImageUrlsSet = oldMediaList.stream()
                .map(CarMedia::getUrl)
                .collect(Collectors.toSet());

        // 提取新的图片URL集合
        Set<String> newImageUrlsSet = newImageUrls != null ? newImageUrls.stream().collect(Collectors.toSet()) : new java.util.HashSet<>();

        // 找出需要从COS和数据库中删除的图片
        List<String> urlsToDelete = oldMediaList.stream()
                .filter(media -> !newImageUrlsSet.contains(media.getUrl()))
                .map(CarMedia::getUrl)
                .collect(Collectors.toList());

        // 找出需要添加到数据库的新图片
        List<String> urlsToAdd = newImageUrlsSet.stream()
                .filter(url -> !oldImageUrlsSet.contains(url))
                .collect(Collectors.toList());

        // 3. 删除COS上的旧文件
        for (String url : urlsToDelete) {
            cosService.deleteFile(url);
        }

        // 4. 更新数据库中的 car_media 表
        // 简单粗暴的方式：先删除所有旧记录，再插入所有新记录
        // 优点：逻辑简单，确保新旧列表完全同步
        // 缺点：如果图片数量多，且只有少量变化，效率较低
        carMediaMapper.delete(new QueryWrapper<CarMedia>().eq("car_id", carId));

        if (newImageUrls != null && !newImageUrls.isEmpty()) {
            for (int i = 0; i < newImageUrls.size(); i++) {
                String imageUrl = newImageUrls.get(i);
                CarMedia media = new CarMedia();
                media.setCarId(carId);
                media.setType(1);
                media.setUrl(imageUrl);
                media.setCreatedAt(new Date());
//                media.setIsMain(i); // 第一张照片设为主图
                media.setOrderIndex(i + 1); // 设置排序
                carMediaMapper.insert(media);
            }
        }
        return true;
    }

    @Override
    @Transactional // 开启事务
    public boolean deleteCar(Integer carId) {
        // 1. 查询所有关联的媒体记录，以便从COS删除文件
        QueryWrapper<CarMedia> mediaQueryWrapper = new QueryWrapper<>();
        mediaQueryWrapper.eq("car_id", carId);
        List<CarMedia> mediaList = carMediaMapper.selectList(mediaQueryWrapper);

        // 2. 从COS删除实际文件
        if (mediaList != null && !mediaList.isEmpty()) {
            for (CarMedia media : mediaList) {
                cosService.deleteFile(media.getUrl());
            }
        }
        // 3. 从数据库删除 car_media 表的记录（由于外键 ON DELETE CASCADE，这步可以省略，但显式删除更清晰）
        // carMediaMapper.delete(mediaQueryWrapper); // 如果外键设置了ON DELETE CASCADE，则不需要手动删除

        // 4. 从数据库删除 cars 表的记录
        // 由于 car_media 表的外键设置了 ON DELETE CASCADE，删除 cars 表记录会自动删除关联的 car_media 记录
        int rowsAffected = carMapper.deleteById(carId);
        return rowsAffected > 0;
    }


    // 随机生成6位汽车编号（可重复）
    private String generateRandomCarNumber() {
        Random random = new Random();
        int num = 100000 + random.nextInt(900000); // 生成 100000~999999
        return String.valueOf(num);
    }


    /**
     * 查询所有已上架的汽车列表，包含主图
     *
     * @param pageNum  页码
     * @param pageSize 每页记录数
     * @return 已上架汽车列表
     */
    @Override
    public IPage<CarListVO> listPublishedCarsWithMainImage(int pageNum, int pageSize) {
        // 创建分页对象
        IPage<CarListVO> page = new Page<>(pageNum, pageSize);

        // 调用Mapper方法，并传入分页对象
        return carMapper.selectPublishedCarsWithMainImage(page);
    }


    /**
     * 查询指定发布人ID发布的已上架汽车列表，包含主图
     *
     * @param publisherId 发布人ID
     * @return 汽车列表（包含主图URL）
     */
    @Override
    public List<MyCarListVO> listCarsByPublisherId(Integer publisherId) {
        LambdaQueryWrapper<Car> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Car::getPublisherId, publisherId); // 根据发布人ID查询
        List<Car> cars = carMapper.selectList(queryWrapper);
        return cars.stream().map(car -> {
            MyCarListVO myCarListVO = new MyCarListVO();
            BeanUtils.copyProperties(car, myCarListVO);
            // Fetch main image URL
            carMediaMapper.selectMediaByCarId(car.getCarId()).stream()
                    .filter(media -> media.getOrderIndex() == 1)
                    .findFirst()
                    .ifPresent(mainImage -> myCarListVO.setMainImageUrl(mainImage.getUrl()));
            return myCarListVO;
        }).collect(Collectors.toList());
    }

    /**
     * 根据车辆ID查询汽车详情，包含所有相关图片
     *
     * @param carId 车辆ID
     * @return 汽车详情，如果不存在则返回null
     */
    @Override
    public CarVO getCarDetailsWithMedia(Integer carId) {
        Car car = carMapper.selectById(carId);
        if (car == null) {
            return null;
        }
        CarVO carVO = new CarVO();
        BeanUtils.copyProperties(car, carVO);
        // Get all media (images and videos) for the car
        List<CarMedia> mediaList = carMediaMapper.selectMediaByCarId(carId);
        // Set main image URL if available
        mediaList.stream()
                .filter(media -> media.getOrderIndex()== 1 && media.getType().equals(1))
                .findFirst()
                .ifPresent(mainImage -> carVO.setMainImageUrl(mainImage.getUrl()));
        // Fetch all media for the car
        List<CarMedia> allMedia = carMediaMapper.selectMediaByCarId(carId);
        carVO.setMediaList(allMedia); // This requires CarVO to have a `mediaList` field.

        return carVO;
    }

    /**
     * 根据标题模糊查询已上架的汽车列表，包含主图
     *
     * @param title 标题关键字
     * @return 汽车列表
     */
    @Override
    public IPage<CarListVO> listPublishedCarsByTitleFuzzy( String province,
                                                       String city,
                                                       String district,
                                                       String title,
                                                       int pageNum,
                                                       int pageSize) {
        // 创建分页对象
        IPage<CarListVO> page = new Page<>(pageNum, pageSize);
        return carMapper.selectPublishedCarsByRegionAndTitleFuzzy(province, city, district, title, page);
    }

    /**
     * 根据汽车编号查询已上架的汽车列表，包含主图
     *
     * @param carNumber 汽车编号
     * @return 汽车列表
     */
    @Override
    public List<CarVO> listPublishedCarsByCarNumber(String carNumber) {
        return carMapper.selectPublishedCarsByCarNumber(carNumber);
    }

    /**
     * 根据汽车品牌查询已上架的汽车列表，包含主图
     *
     * @param brand 汽车品牌
     * @return 汽车列表
     */
    @Override
    public IPage<CarListVO> listPublishedCarsByBrand(String brand,int pageNum, int pageSize) {
        // 创建分页对象
        IPage<CarListVO> page = new Page<>(pageNum, pageSize);
        return carMapper.selectPublishedCarsByBrand(brand,page);
    }

    /**
     * 根据地区（省市区）查询已上架的汽车列表，包含主图
     *
     * @param province 省份
     * @param city     城市
     * @param district 区县
     * @return 汽车列表
     */
    @Override
    public List<CarVO> listPublishedCarsByRegion(String province, String city, String district) {
        return carMapper.selectPublishedCarsByRegion(province, city, district);
    }

    /**
     * 根据地区（省市区）和品牌查询已上架的汽车列表，包含主图
     *
     * @param province 省份
     * @param city     城市
     * @param district 区县
     * @param brand    品牌
     * @return 汽车列表
     */
//    @Override
//    public List<CarVO> listPublishedCarsByRegionAndBrand(String province, String city, String district, String brand) {
//        LambdaQueryWrapper<Car> queryWrapper = new LambdaQueryWrapper<>();
//        queryWrapper.eq(Car::getStatus, 1); // Status must be 1 (published)
//        if (StringUtils.hasText(province)) {
//            queryWrapper.eq(Car::getProvince, province);
//        }
//        if (StringUtils.hasText(city)) {
//            queryWrapper.eq(Car::getCity, city);
//        }
//        if (StringUtils.hasText(district)) {
//            queryWrapper.eq(Car::getDistrict, district);
//        }
//        if (StringUtils.hasText(brand)) {
//            queryWrapper.eq(Car::getBrand, brand);
//        }
//
//        // Execute the query and manually map to CarVO to include main image
//        List<Car> cars = carMapper.selectList(queryWrapper);
//        return cars.stream().map(car -> {
//            CarVO carVO = new CarVO();
//            BeanUtils.copyProperties(car, carVO);
//            // Fetch main image URL
//            carMediaMapper.selectMediaByCarId(car.getCarId()).stream()
//                    .filter(media -> media.getOrderIndex()== 1 && media.getType().equals(1))
//                    .findFirst()
//                    .ifPresent(mainImage -> carVO.setMainImageUrl(mainImage.getUrl()));
//            return carVO;
//        }).collect(Collectors.toList());
//    }

    /**
     * 根据地区（省市区）和标题模糊查询已上架的汽车列表，包含主图
     *
     * @param province 省份
     * @param city     城市
     * @param district 区县
     * @param title    标题关键字
     * @return 汽车列表
     */
//    @Override
//    public IPage<CarVO> listPublishedCarsByRegionAndTitleFuzzy(String province, String city, String district, String title) {
//        LambdaQueryWrapper<Car> queryWrapper = new LambdaQueryWrapper<>();
//        queryWrapper.eq(Car::getStatus, 1); // Status must be 1 (published)
//        if (StringUtils.hasText(province)) {
//            queryWrapper.eq(Car::getProvince, province);
//        }
//        if (StringUtils.hasText(city)) {
//            queryWrapper.eq(Car::getCity, city);
//        }
//        if (StringUtils.hasText(district)) {
//            queryWrapper.eq(Car::getDistrict, district);
//        }
//        if (StringUtils.hasText(title)) {
//            queryWrapper.like(Car::getTitle, title);
//        }
//
//        // Execute the query and manually map to CarVO to include main image
//       IPage<Car> cars = carMapper.selectList(queryWrapper);
//        return cars.stream().map(car -> {
//            CarVO carVO = new CarVO();
//            BeanUtils.copyProperties(car, carVO);
//            // Fetch main image URL
//            carMediaMapper.selectMediaByCarId(car.getCarId()).stream()
//                    .filter(media -> media.getOrderIndex()== 1 && media.getType().equals(1))
//                    .findFirst()
//                    .ifPresent(mainImage -> carVO.setMainImageUrl(mainImage.getUrl()));
//            return carVO;
//        }).collect(Collectors.toList());
//    }

    /**
     * 多条件查询已上架的汽车列表，包含主图
     *
     * @param queryDTO 查询条件DTO
     * @return 汽车列表
     */
    @Override
    public List<CarVO> listPublishedCarsMultiCondition(CarQueryDTO queryDTO) {
        LambdaQueryWrapper<Car> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Car::getStatus, 1); // Status must be 1 (published)

        if (StringUtils.hasText(queryDTO.getTitle())) {
            queryWrapper.like(Car::getTitle, queryDTO.getTitle());
        }
        if (StringUtils.hasText(queryDTO.getBrand())) {
            queryWrapper.eq(Car::getBrand, queryDTO.getBrand());
        }
        if (StringUtils.hasText(queryDTO.getProvince())) {
            queryWrapper.eq(Car::getProvince, queryDTO.getProvince());
        }
        if (StringUtils.hasText(queryDTO.getCity())) {
            queryWrapper.eq(Car::getCity, queryDTO.getCity());
        }
        if (StringUtils.hasText(queryDTO.getDistrict())) {
            queryWrapper.eq(Car::getDistrict, queryDTO.getDistrict());
        }
        if (queryDTO.getMaxMileage() != null) {
            queryWrapper.le(Car::getMileage, queryDTO.getMaxMileage());
        }
        if (queryDTO.getSeats() != null) {
            queryWrapper.eq(Car::getSeats, queryDTO.getSeats());
        }
        if (queryDTO.getMinPrice() != null) {
            queryWrapper.ge(Car::getPrice, queryDTO.getMinPrice());
        }
        if (queryDTO.getMaxPrice() != null) {
            queryWrapper.le(Car::getPrice, queryDTO.getMaxPrice());
        }
        if (queryDTO.getManufactureYear() != null) {
            queryWrapper.eq(Car::getManufactureYear, queryDTO.getManufactureYear());
        }
        // Assuming registrationYear means the year part of the registration date
        if (queryDTO.getRegistrationYear() != null) {
            queryWrapper.apply("YEAR(registration) = {0}", queryDTO.getRegistrationYear());
        }
        if (StringUtils.hasText(queryDTO.getExterior())) {
            queryWrapper.eq(Car::getExterior, queryDTO.getExterior());
        }
        if (StringUtils.hasText(queryDTO.getInterior())) {
            queryWrapper.eq(Car::getInterior, queryDTO.getInterior());
        }
        if (queryDTO.getPower() != null) {
            queryWrapper.eq(Car::getPower, queryDTO.getPower());
        }
        if (queryDTO.getMinKilometer() != null) {
            queryWrapper.ge(Car::getKilometer, queryDTO.getMinKilometer());
        }
        if (queryDTO.getTransferCount() != null) {
            queryWrapper.eq(Car::getTransferCount, queryDTO.getTransferCount());
        }

        // Execute the query and manually map to CarVO to include main image
        List<Car> cars = carMapper.selectList(queryWrapper);
        return cars.stream().map(car -> {
            CarVO carVO = new CarVO();
            BeanUtils.copyProperties(car, carVO);
            // Fetch main image URL
            carMediaMapper.selectMediaByCarId(car.getCarId()).stream()
                    .filter(media -> media.getOrderIndex()== 1 && media.getType().equals(1))
                    .findFirst()
                    .ifPresent(mainImage -> carVO.setMainImageUrl(mainImage.getUrl()));
            return carVO;
        }).collect(Collectors.toList());
    }

    /**
     * 更新汽车信息
     * @param car 待更新的汽车对象
     * @return 是否更新成功
     */
    @Override
    public boolean updateCar(Car car) {
        return this.updateById(car);
    }

    /**
     * 汽车下架：将汽车状态设置为已下架(status=2)
     * @param carId 车辆ID
     * @return 是否下架成功
     */
    @Override
    public boolean offlineCar(Integer carId) {
        // 先查询车辆是否存在
        Car existingCar = carMapper.selectById(carId);
        // 设置状态为下架(2)并更新时间
        existingCar.setStatus(2);
        existingCar.setUpdatedAt(new Date());
        // 执行更新操作
        int rowsAffected = carMapper.updateById(existingCar);
        return rowsAffected > 0;
    }

    /**
     * 汽车重新发布：将汽车状态设置为待审核(status=0)
     *
     * @param carId 车辆ID
     * @return 是否发布成功
     */
    @Override
    public boolean publishCar(Integer carId) {
        // 先查询车辆是否存在
        Car existingCar = carMapper.selectById(carId);
        // 设置状态为已上架(1)并更新时间
        existingCar.setStatus(0);
        existingCar.setUpdatedAt(new Date());
        // 执行更新操作
        int rowsAffected = carMapper.updateById(existingCar);
        return rowsAffected > 0;
    }

}




